#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
// 游戏窗口尺寸
#define WIDTH 40 //2:1 更像正方形
#define HEIGHT 20
// 蛇的最大长度
#define MAX_LENGTH 100
// 方向枚举
typedef enum {
    STOP,
    LEFT,
    RIGHT,
    UP,
    DOWN
} Direction;
// 蛇结构体
typedef struct {
    int x[MAX_LENGTH];
    int y[MAX_LENGTH];
    int length;
    Direction dir;
} Snake;
// 食物结构体
typedef struct {
    int x;
    int y;
} Food;
// 函数声明
void init_game(Snake *snake, Food *food);
void draw_map(Snake *snake, Food *food, int speed_level);
void move_snake(Snake *snake);
void generate_food(Snake *snake, Food *food);
void change_direction(Snake *snake, int key);
int check_collision(Snake *snake);
void save_score(int score);
int load_score();
void welcome_to_game();
void print_snake();
void print_GAMEOVER();
void score_and_tips(int score, int high_score, int speed_level);
void explanation();
// 新增函数声明
int biteself(Snake *snake);
void cantcrosswall(Snake *snake, int *game_over);
void speedup(int *sleeptime, int *speed_level);
void speeddown(int *sleeptime, int *speed_level);
void snakemove(Snake *snake);
void keyboardControl(Snake *snake, int *sleeptime, int *score, int *paused, int *speed_level);
void game_over_screen(int score, int high_score);

int main() {
    Snake snake;
    Food food;
    int game_over = 0;
    int score = 0;
    int high_score = load_score();
    int sleeptime = 180; // 修改: 将初始时间间隔恢复为180
    int paused = 0;
    int speed_level = 1; // 初始速度等级为1

    welcome_to_game();
    init_game(&snake, &food);

    while (!game_over) {
        if (!paused) {
            draw_map(&snake, &food, speed_level);
            score_and_tips(score, high_score, speed_level);

            keyboardControl(&snake, &sleeptime, &score, &paused, &speed_level);
            snakemove(&snake);
            move_snake(&snake);

            if (snake.x[0] == food.x && snake.y[0] == food.y) {
                score += speed_level; // 增加的分数与速度等级一致
                if (score > high_score) {
                    high_score = score;
                    save_score(high_score);
                }
                generate_food(&snake, &food);

                if (snake.length < MAX_LENGTH) {
                    snake.length++;
                } else {
                    printf("蛇已达到最大长度，无法继续增长！\n");
                }

                speedup(&sleeptime, &speed_level);
            }

            if (check_collision(&snake)) {
                game_over = 1;
            }

            Sleep(sleeptime); // 保留这句作为唯一的速度控制
        } else {
            // 显示暂停信息
            system("cls");
            draw_map(&snake, &food, speed_level);
            score_and_tips(score, high_score, speed_level);
            printf("\n\n          暂停中...\n          按任意键继续...\n");
            _getch();
            paused = 0;
        }
    }

    // 游戏失败界面
    game_over_screen(score, high_score);

    return 0;
}
void init_game(Snake *snake, Food *food) {
    // 初始化蛇的位置和方向
    snake->length = 3; // 修改: 将初始长度改为3
    snake->x[0] = WIDTH / 2;
    snake->y[0] = HEIGHT / 2;
    snake->x[1] = WIDTH / 2 - 1; // 添加: 初始化第二个身体位置
    snake->y[1] = HEIGHT / 2;
    snake->x[2] = WIDTH / 2 - 2; // 添加: 初始化第三个身体位置
    snake->y[2] = HEIGHT / 2;
    snake->dir = STOP;

    // 初始化食物的位置
    generate_food(snake, food);
}
void draw_map(Snake *snake, Food *food, int speed_level) {
    // 绘制地图
    system("cls");
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // 获取控制台句柄

    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            if (i == 0 || i == HEIGHT - 1 || j == 0 || j == WIDTH - 1) {
                printf("#");
            } else if (i == food->y && j == food->x) {
                SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); // 设置食物颜色为绿色
                printf("*");
                SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); // 恢复默认颜色
            } else {
                int k;
                for (k = 0; k < snake->length; k++) {
                    if (i == snake->y[k] && j == snake->x[k]) {
                        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN); // 设置蛇颜色为黄色
                        printf("O");
                        SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); // 恢复默认颜色
                        break;
                    }
                }
                if (k == snake->length) {
                    printf(" ");
                }
            }
        }
        printf("\n");
    }
}
void move_snake(Snake *snake) {
    // 移动蛇的身体
    for (int i = snake->length - 1; i > 0; i--) {
        snake->x[i] = snake->x[i - 1];
        snake->y[i] = snake->y[i - 1];
    }

    // 根据方向移动蛇头
    switch (snake->dir) {
        case LEFT:
            snake->x[0]--;
            break;
        case RIGHT:
            snake->x[0]++;
            break;
        case UP:
            snake->y[0]--;
            break;
        case DOWN:
            snake->y[0]++;
            break;
    }
}

void generate_food(Snake *snake, Food *food) {
    // 随机生成食物位置
    do {
        food->x = rand() % (WIDTH - 2) + 1;
        food->y = rand() % (HEIGHT - 2) + 1;
    } while (check_collision(snake));
}

void change_direction(Snake *snake, int key) {
    // 改变蛇的移动方向
    switch (key) {
        case 'a':
            if (snake->dir != RIGHT) {
                snake->dir = LEFT;
            }
            break;
        case 'd':
            if (snake->dir != LEFT) {
                snake->dir = RIGHT;
            }
            break;
        case 'w':
            if (snake->dir != DOWN) {
                snake->dir = UP;
            }
            break;
        case 's':
            if (snake->dir != UP) {
                snake->dir = DOWN;
            }
            break;
    }
}
int check_collision(Snake *snake) {
    // 检测碰撞
    if (snake->x[0] <= 0 || snake->x[0] >= WIDTH - 1 ||
        snake->y[0] <= 0 || snake->y[0] >= HEIGHT - 1) {
        return 1;
    }

    for (int i = 1; i < snake->length; i++) {
        if (snake->x[0] == snake->x[i] && snake->y[0] == snake->y[i]) {
            return 1;
        }
    }

    return 0;
}
void save_score(int score) {
    // 保存最高分
    FILE *file = fopen("highscore.txt", "w");
    if (file != NULL) {
        fprintf(file, "%d", score);
        fclose(file);
    }
}
int load_score() {
    // 读取最高分
    int score = 0;
    FILE *file = fopen("highscore.txt", "r");
    if (file != NULL) {
        fscanf(file, "%d", &score);
        fclose(file);
    }
    return score;
}

// 判断蛇是否咬到自己
int biteself(Snake *snake) {
    for (int i = 1; i < snake->length; i++) {
        if (snake->x[0] == snake->x[i] && snake->y[0] == snake->y[i]) {
            return 1;
        }
    }
    return 0;
}

// 判断蛇是否撞到墙
void cantcrosswall(Snake *snake, int *game_over) {
    if (snake->x[0] <= 0 || snake->x[0] >= WIDTH - 1 ||
        snake->y[0] <= 0 || snake->y[0] >= HEIGHT - 1) {
        *game_over = 1;
    }
}

// 设置蛇加速前进
void speedup(int *sleeptime, int *speed_level) {
    if (*sleeptime > 30) { // 修改: 设置加速阈值为90
        *sleeptime -= 30; // 修改: 每次加速减少30
            if(*speed_level<5) {
                (*speed_level)++;
            }
    }
}

// 设置蛇减速前进
void speeddown(int *sleeptime, int *speed_level) {
    if (*sleeptime < 270) {
        *sleeptime += 30; // 修改: 每次减速增加30
        if (*speed_level > 1) {
            (*speed_level)--;
        }
    }
}
// 不按键时设置蛇的前进方向
void snakemove(Snake *snake) {
    // 如果蛇没有方向，则默认向右移动
    if (snake->dir == STOP) {
        snake->dir = RIGHT;
    }
}
// 通过键盘按键控制蛇的方向
void keyboardControl(Snake *snake, int *sleeptime, int *score, int *paused, int *speed_level) {
    if (_kbhit()) {
        int key = _getch(); // 第一次读取

        // 处理扩展键（如方向键）
        if (key == 0 || key == 0xE0) {
            key = _getch(); // 第二次读取实际扫描码

            switch (key) {
                case 72: // 上箭头键：加速
                    speedup(sleeptime, speed_level);
                    break;
                case 80: // 下箭头键：减速
                    speeddown(sleeptime, speed_level);
                    break;
                case 75: // 左箭头
                    if (snake->dir != RIGHT) {
                        snake->dir = LEFT;
                    }
                    break;
                case 77: // 右箭头
                    if (snake->dir != LEFT) {
                        snake->dir = RIGHT;
                    }
                    break;
                default:
                    break;
            }
        } else {
            // 处理普通字符按键
            switch (key) {
                case 'a':
                    if (snake->dir != RIGHT) {
                        snake->dir = LEFT;
                    }
                    break;
                case 'd':
                    if (snake->dir != LEFT) {
                        snake->dir = RIGHT;
                    }
                    break;
                case 'w':
                    if (snake->dir != DOWN) {
                        snake->dir = UP;
                    }
                    break;
                case 's':
                    if (snake->dir != UP) {
                        snake->dir = DOWN;
                    }
                    break;
                case 27: // ESC 键
                    *paused = 1;
                    break;
                // 其他按键可以继续添加
                default:
                    break;
            }
        }
    }
}
// 游戏失败界面
void game_over_screen(int score, int high_score) {
    system("cls");
    print_GAMEOVER();
    
    printf("最终得分: %d\n", score);

    if (score < high_score) {
        printf("继续努力吧~你离最高分还差: %d 分\n", high_score - score);
    } else {
        printf("创纪录啦！最高分被你刷新啦，真棒！！！\n");
    }

    printf("\n1. 重玩\n2. 退出游戏\n");
    int choice = _getch() - '0';

    switch (choice) {
        case 1:
            main();
            break;
        case 2:
            exit(0);
        default:
            printf("输入错误，请重新选择...\n");
            Sleep(1000);
            game_over_screen(score, high_score);
    }
}
// 游戏说明界面
void explanation() {
    system("cls");
    printf("游戏说明：\n");
    printf("1. 使用 'WASD' 控制蛇的移动方向。\n");
    printf("2.按 上箭头 键加速，按 下箭头 键减速。\n");
    printf("3.吃到食物后总得分以速度等级为单位增加。\n");
    printf("4. 蛇撞到墙或咬到自己会导致游戏失败。\n");
    printf("5. 按 ESC 键暂停游戏。\n");
    printf("\n按任意键返回主菜单...");
    _getch();
    welcome_to_game();
}
void welcome_to_game() {
    system("cls");
    print_snake();
    printf("\n");
    printf("1. 开始游戏\n");
    printf("2. 游戏说明\n");
    printf("3. 退出游戏\n");
    printf("请选择: ");
    int choice = _getch() - '0';

    switch (choice) {
        case 1:
            break;
        case 2:
            explanation();
            break;
        case 3:
            exit(0);
        default:
            printf("无效的选择。按任意键继续...");
            _getch();
            welcome_to_game();
    }
}
void print_GAMEOVER() {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);

    printf(" _____   ___  ___  ___ _____ _____  _   _ ___________   _ _ _ \n");
    printf("|  __ \\ / _ \\ |  \\/  ||  ___|  _  || | | |  ___| ___ \\ | | | |\n");
    printf("| |  \\/| /_\\ \\| .  . || |__ | | | || | | | |__ | |_/ / | | | |\n");
    printf("| | __ |  _  || |\\/| ||  __|| | | || | | |  __||    /  | | | |\n");
    printf("| |_\\ \\| | | || |  | || |___\\ \\_/ / \\ \\/ / |___| |\\ \\  |_|_|_|\n");
    printf(" \\____/\\_| |_/\\_|  |_/\\____/ \\___/   \\__/|____/\\_| \\_\\ (_|_|_)\n");

    // Reset to default text color
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}void print_snake() {
    // 绘制 "GreedySnake" 的字符画
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);

    printf(" _____                   _       _____                     \n");
    printf("|  __ \\                 | |     /  ___|            _   \n");
    printf("| |  \\/_ __ ___  ___  __| |_   _\\`--. _ ___   __ _| | _____ \n");
    printf("| | __| '__/ _ \\/ _ \\/ _` | | | |`--. \\ '_ \\ / _` | |/ / _ \\ \n");
    printf("| |_\\ \\ | |  __/  __/ (_| | |_| /\\__/ / | | | (_| |   <  __/ \n");
    printf(" \\____/_|  \\___|\\___|\\__,_|\\__, \\____/|_| |_|\\__,_|_|\\_\\___| \n");
    printf("                            __/ |                           \n");
    printf("                           |___/                            \n");

    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
void score_and_tips(int score, int high_score, int speed_level) {
    // 打印得分和提示信息
    printf("当前得分: %d   历史最高分: %d\n", score, high_score);
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // 获取控制台句柄
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED); // 设置速度等级颜色为红色
    printf("速度等级: %d\n", speed_level);
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); // 恢复默认颜色
    printf("使用WASD键来控制蛇的方向.\n");
    printf("按Esc键 暂停/恢复 游戏.\n");
    printf("按 上/下箭头键 进行加/减速. \n");
}



